﻿using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace OMR.Crawler.Core.Crawlers
{
    public class FSCrawler : CrawlerBase
    {
        private readonly string _rootDirectory;
        private readonly string[] _allowedFileExtensions;

        public FSCrawler(MyCollection settings)
            : base(settings)
        {
            _rootDirectory = (string)settings.GetItem("EntryPoint").Value;
            CrawlQueue.Enqueue(new CrawlWork() { EntryPoint = _rootDirectory, DeepCount = 0 });

            _allowedFileExtensions = new string[] { "txt", "pdf", "htm", "html", "cs", "vb", "xml", "doc", "docx", "xls", "xlsx", "csv", "ppt", "pptx", "rtf" };
        }

        public override void Begin()
        {
            base.Begin((currentWork) => Iterate(currentWork));
        }

        private void Iterate(CrawlWork currentWork)
        {
            try
            {
                foreach (string subDir in Directory.GetDirectories(currentWork.EntryPoint))
                {
                    var subCrawlWork = new CrawlWork();
                    subCrawlWork.DeepCount = currentWork.DeepCount + 1;
                    subCrawlWork.EntryPoint = subDir;

                    CrawlQueue.Enqueue(subCrawlWork);
                }
            }
            catch (Exception exception)
            {
                CrawlError(exception,currentWork.EntryPoint);
            }

            string[] files = null;

            try
            {
                // Get only allowed files by file types
                files = Directory.GetFiles(currentWork.EntryPoint)
                                    .Where(f => Path.GetExtension(f).Length > 0 && _allowedFileExtensions.Contains(Path.GetExtension(f).Substring(1)))
                                    .ToArray();
            }
            catch (Exception exception)
            {
                CrawlError(exception, currentWork.EntryPoint);
                return;
            }

            if (files != null)
            {
                Parallel.ForEach(files, (file) =>
                {
                    try
                    {
                        var subCrawlWork = new CrawlWork();
                        subCrawlWork.DeepCount = currentWork.DeepCount + 1;
                        subCrawlWork.EntryPoint = file;
                        subCrawlWork.Content = File.ReadAllBytes(file);
                        subCrawlWork.MimeType = MimeTypes.GetMimeTypeName(Path.GetExtension(file).Substring(1));
                        subCrawlWork.Title = Path.GetFileNameWithoutExtension(file);

                        ItemCrawled(subCrawlWork);
                    }
                    catch (Exception exception)
                    {
                        CrawlError(exception, currentWork.EntryPoint);
                    }
                });
            }
        }
    }

}